﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using TwinCAT.Ads;
using static OfficeOpenXml.ExcelErrorValue;

namespace IP20.Procdure
{
    internal class TwinCatTool
    {
        private static bool connected = false;
        private static readonly object locker = new object();
        private static TcAdsClient client;

        private static List<int> listhDI;
        private static List<int> listhDO;
        private static List<int> listhAI;
        private static List<int> listhAO;
        private static List<int> listhDevSts;

        //private static int waitTime = 100;
        private static int hDI1;

        private static int hDO1;
        private static int hAI1;
        private static int hAO1;
        private static int hDevSts1;
        private static int hDI2;
        private static int hDO2;
        private static int hAI2;
        private static int hAO2;
        private static int hDevSts2;

        public static void Connect()
        {
            lock (locker)
            {
                if (connected)
                {
                    return;
                }
                client = new TcAdsClient();
                client.Connect(851);
                hDI1 = client.CreateVariableHandle("GVL.DISts1");
                hDO1 = client.CreateVariableHandle("GVL.DOSts1");
                hAI1 = client.CreateVariableHandle("GVL.AISts1");
                hAO1 = client.CreateVariableHandle("GVL.AOSts1");
                hDevSts1 = client.CreateVariableHandle("GVL.DevSts1");

                hDI2 = client.CreateVariableHandle("GVL.DISts2");
                hDO2 = client.CreateVariableHandle("GVL.DOSts2");
                hAI2 = client.CreateVariableHandle("GVL.AISts2");
                hAO2 = client.CreateVariableHandle("GVL.AOSts2");
                hDevSts2 = client.CreateVariableHandle("GVL.DevSts2");

                listhDI = new List<int>();
                listhDO = new List<int>();
                listhAI = new List<int>();
                listhAO = new List<int>();
                listhDevSts = new List<int>();

                listhDI.Add(hDI1);
                listhDI.Add(hDI2);

                listhDO.Add(hDO1);
                listhDO.Add(hDO2);

                listhAI.Add(hAI1);
                listhAI.Add(hAI2);

                listhAO.Add(hAO1);
                listhAO.Add(hAO2);

                listhDevSts.Add(hDevSts1);
                listhDevSts.Add(hDevSts2);
                connected = true;
            }
        }

        public static UInt32 GetDevStatus(int index)
        {
            lock (locker)
            {
                UInt32 val;
                val = (UInt32)client.ReadAny(listhDevSts[index], typeof(UInt32));
                return val;
            }
        }

        public static bool[] GetDI(int index, int diCount)
        {
            lock (locker)
            {
                var obj = client.ReadAny(listhDI[index], typeof(bool[]), new int[] { diCount });
                return ((bool[])obj);
            }
        }

        public static bool[] GetDO(int index, int doCount)
        {
            lock (locker)
            {
                var obj = client.ReadAny(listhDO[index], typeof(bool[]), new int[] { doCount });
                return ((bool[])obj);
            }
        }

        public static void SetDO(int index, bool[] values)
        {
            lock (locker)
            {
                client.WriteAny(listhDO[index], values);
            }
        }

        public static void SetAO(int index, Int16[] values)
        {
            lock (locker)
            {
                client.WriteAny(listhAO[index], values);
            }
        }

        public static void SetAO<T>(int index, T[] values)
        {
            lock (locker)
            {
                client.WriteAny(listhAO[index], values);
            }
        }

        public static T[] GetAI<T>(int index, int aiCount)
        {
            lock (locker)
            {
                var obj = client.ReadAny(listhAI[index], typeof(Int16[]), new int[] { aiCount });
                return ((T[])obj);
            }
        }

        public static void Close()
        {
            lock (locker)
            {
                if (!connected)
                {
                    return;
                }
                client.DeleteVariableHandle(hDI1);
                client.DeleteVariableHandle(hDO1);
                client.DeleteVariableHandle(hAI1);
                client.DeleteVariableHandle(hAO1);
                client.DeleteVariableHandle(hDevSts1);
                client.DeleteVariableHandle(hDI2);
                client.DeleteVariableHandle(hDO2);
                client.DeleteVariableHandle(hAI2);
                client.DeleteVariableHandle(hAO2);
                client.DeleteVariableHandle(hDevSts2);
                client.Disconnect();
                connected = false;
            }
        }
    }
}